package com.richard.base.util

import android.content.Context
import android.os.Environment
import java.io.*
import java.text.DecimalFormat

/**
 ***************************************
 * 项目名称:Giggle
 * @Author wuzhiguo
 * 邮箱：wuzhiguo@ksjgs.com
 * 创建时间: 2020/8/14     1:59 PM
 * 用途:
 ***************************************
 */
object FileUtil {

    var rootFilePath: String? = null
    var rootCachePath: String? = null
    lateinit var appInternalCachePath: String

    /**
     * 初始化一次即可
     * @param context Context
     */
    fun initFile(context: Context) {
        rootFilePath = getFileRootPath(context)
        rootCachePath = getCacheRootPath(context)
        appInternalCachePath = getInternalCacheRootPath(context)
    }

    private fun getInternalCacheRootPath(context: Context): String {
        return context.cacheDir.absolutePath
    }

    /**
     * 转换文件大小
     *
     * @param fileLen 单位B
     * @return
     */
    fun fileSize2Str(fileLen: Long): String {
        val df = DecimalFormat("0.0")
        var fileSizeString = ""

        fileSizeString = if (fileLen < 1073741824) {
            df.format(fileLen.toDouble() / 1048576) + "M"
        } else {
            df.format(fileLen.toDouble() / 1073741824) + "G"
        }
        return fileSizeString
    }

    /**
     * 检测Sdcard是否存在
     * @return
     */
    fun isSdCardExist(): Boolean {
        return Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()
    }

    /**
     * 判断文件是否存在
     * @return Boolean
     */
    fun isExist(path: String): Boolean {
        if (path == null || path.isBlank()) {
            return false
        }
        var file = File(path)
        return file.exists()
    }


    /**
     * 获取文件夹大小
     * @return Long
     */
    fun getDirSize(vararg paths: String): Long {
        var sizeCount: Long = 0
        for (filePath in paths) {
            val size = getDirSize(File(filePath))
            sizeCount += size
        }
        return sizeCount
    }

    /**
     * 获取文件夹大小
     * @return Long
     */
    private fun getDirSize(file: File): Long {
        // 判断文件是否存在
        if (file.exists()) {
            // 如果是目录则递归计算其内容的总大小
            if (file.isDirectory) {
                val children = file.listFiles()
                var size: Long = 0
                for (f in children) size += getDirSize(f)
                return size
            } else {
                return file.length()
            }
        } else {
            return 0
        }
    }


    /**
     * 创建文件夹
     */
    fun createFolder(filePath: String): File {
        //文件路径必须在 rootFilePath 或者 rootCachePath之下
        if (!filePath.contains(rootFilePath!!)
            && !filePath.contains(rootCachePath!!)
            && !filePath.contains(appInternalCachePath)
        ) {
            throw IllegalArgumentException("文件路径不合法")
        }

        val file = File(filePath)
        // 如果文件夹不存在，就创建它
        if (!file.exists()) {
            file.mkdirs()
        }
        return file
    }


    /**
     * 创建文件
     */
    fun createFile(filePath: String): File {
        //文件路径必须在 rootFilePath 或者 rootCachePath之下
        if (!filePath.contains(rootFilePath!!) && !filePath.contains(rootCachePath!!)) {
            throw IllegalArgumentException("文件路径不合法")
        }

        val file = File(filePath)
        try {
            if (!file.exists()) {
                // 创建父类文件夹
                createFolder(file.parent)
                // 创建文件
                file.createNewFile()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return file
    }


    /**
     * 获取Cache文件夹
     */
    private fun getCacheRootPath(context: Context): String? {
        return if (isSdCardExist()) {
            context.externalCacheDir?.absolutePath
        } else {
            context.cacheDir.absolutePath
        }
    }

    /**
     * 获取File文件夹
     */
    private fun getFileRootPath(context: Context): String? {
        return if (isSdCardExist()) {
            context.getExternalFilesDir("")?.path
        } else {
            context.filesDir.path
        }
    }

    /**
     * 将内容写入文件
     *
     * @param filePath eg:/mnt/sdcard/demo.txt
     * @param content 内容
     * @param isAppend 是否追加
     */
    fun writeFile(filePath: String, content: String, isAppend: Boolean) {
        try {
            val fout = FileOutputStream(filePath, isAppend)
            val bytes = content.toByteArray()
            fout.write(bytes)
            fout.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 文件拷贝
     *
     * @param src 源文件
     * @param desc 目的文件
     */
    fun fileChannelCopy(src: File, desc: File) {

        createFile(desc.absolutePath)
        var fi: FileInputStream? = null
        var fo: FileOutputStream? = null
        try {
            fi = FileInputStream(src)
            fo = FileOutputStream(desc)
            val inChanel = fi.channel // 得到对应的文件通道
            val outChanel = fo.channel // 得到对应的文件通道
            inChanel.transferTo(0, inChanel.size(), outChanel) // 连接两个通道，并且从in通道读取，然后写入out通道
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                fo?.close()
                fi?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }


    /**
     * 清空文件夹内的文件， 不包括根目录
     * @param directoryFile File?
     */
    fun deleteChildFiles(directoryFile: File?) {
        if (directoryFile != null && directoryFile.isDirectory) {
            val childFiles = directoryFile.listFiles()
            for (child in childFiles) {
                deleteFileOrDirectory(child)
            }
        }
    }

    /**
     * 删除指定文件，如果是文件夹，则递归删除（包括根目录）
     *
     * @param file
     * @return
     */
    fun deleteFileOrDirectory(file: File?): Boolean {
        try {
            if (file != null && file.isFile) {
                return file.delete()
            }
            if (file != null && file.isDirectory) {
                val childFiles = file.listFiles()
                // 删除空文件夹
                if (childFiles == null || childFiles.size == 0) {
                    return file.delete()
                }
                // 递归删除文件夹下的子文件
                for (i in childFiles.indices) {
                    deleteFileOrDirectory(childFiles[i])
                }
                return file.delete()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    /**
     * 获取文件内容
     * @param path
     * @return
     */
    fun getFileOutputString(path: String, charset: String): String? {
        try {
            val file = File(path)
            val bufferedReader = BufferedReader(
                InputStreamReader(FileInputStream(file), charset), 8192
            )
            val sb = StringBuilder()
            var line: String? = null
            while ({ line = bufferedReader.readLine();line }() != null) {
                sb.append("\n").append(line)
            }
            bufferedReader.close()
            return sb.toString()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }
}
